package cc.wanforme.fsync.config.db;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import javax.sql.DataSource;

import cc.wanforme.st.server.util.PathResource;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;

/**数据库库配置用的是这个，单数据源<br>
 * @author wanne
 * 2020年4月26日
 * 
 */
//@ConditionalOnProperty(prefix = "spring.datasource",name = "enable-dynamic",havingValue = "false")
@Configuration
public class DatabaseConfiguration {

	/** 如果要这样注入，该路径只能填一个*/
	@Value("${mybatis-plus.mapper-locations}")
	private String mapper_locations;
	
	@Value("${mybatis-plus.type-aliases-package}")
	private String type_aliases_package;
	
	@Value("${mybatis-plus.configuration.map-underscore-to-camel-case}")
	private boolean configuration_map_underscore_to_camel_case;
	
	@Value("${mybatis-plus.configuration.log-impl}")
	private String configuration_log_impl;

	@Value("${spring.datasource.druid.sqlite.url}")
	private String sqliteUrl;

	@Value("${spring.datasource.druid.sqlite.emptyFile}")
	private String sqliteFile;

	@Primary
	@Bean(name = "datasource")
//	@ConfigurationProperties("spring.datasource.druid.default")
	@ConfigurationProperties("spring.datasource.druid.sqlite")
	public DataSource datasource() throws IOException {
		checkSqliteAndInit();
		return DruidDataSourceBuilder.create().build();
	}

	// 预检查sqlite文件是否存在，不使用内置的数据库文件，复制一个新的出来
	private File checkSqliteAndInit() throws IOException {
		String file = null;
		if(sqliteUrl.startsWith("jdbc:sqlite::resource:")) {
			file = sqliteUrl.substring("jdbc:sqlite::resource:".length());
		} else {
			file = sqliteUrl.substring("jdbc:sqlite:".length());
		}

		// 可以自定义原始文件
		boolean fileExisted = PathResource.isFileExisted(file);
		if(!fileExisted) {
			PathResource.saveClassPathResource(sqliteFile, file);
		}
		return (new File(file)).getAbsoluteFile();
	}

	@Primary
	@Bean(name = "transactionManager")
	public DataSourceTransactionManager transactionManager(@Qualifier("datasource") DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
	
	// 没有 持久层 就不要使用
	@SuppressWarnings("unchecked")
	@Primary
	@Bean(name = "sqlSessionFactory")
	public SqlSessionFactory sqlSessionFactory(@Qualifier("datasource") DataSource masterDataSource)
			throws Exception {
		MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
		sqlSessionFactory.setDataSource(masterDataSource);
		
		// fix: 打包后, mybatis 无法识别 alias
		// 一种解决方式: https://blog.csdn.net/u012954706/article/details/103977335
		// 详细问题: https://blog.csdn.net/taotoxht/article/details/70171542
		sqlSessionFactory.setVfs(com.baomidou.mybatisplus.autoconfigure.SpringBootVFS.class); // mybatis-plus
		//sqlSessionFactory.setVfs(org.mybatis.spring.boot.autoconfigure.SpringBootVFS.class);  // mybatis
		// 如果上面的方式没有效果，那么请使用下面的代码
		VFS.USER_IMPLEMENTATIONS.add(com.baomidou.mybatisplus.autoconfigure.SpringBootVFS.class); // mybatis-plus
		// VFS.USER_IMPLEMENTATIONS.add(org.mybatis.spring.boot.autoconfigure.SpringBootVFS.class); // mybatis


		MybatisConfiguration configuration = new MybatisConfiguration();
		configuration.setJdbcTypeForNull(JdbcType.NULL);
		configuration.setMapUnderscoreToCamelCase(configuration_map_underscore_to_camel_case);
		configuration.setCacheEnabled(false);
		configuration.setLogImpl((Class<? extends Log>) Class.forName(configuration_log_impl));
		
		if(type_aliases_package != null) {
			String[] split = type_aliases_package.split("\\,");
			Arrays.asList(split).forEach( e-> {
				configuration.getTypeAliasRegistry().registerAliases(e.trim());
			});
		}
		
		sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapper_locations));
		sqlSessionFactory.setConfiguration(configuration);
		
		// PerformanceInterceptor(),OptimisticLockerInterceptor()
		// 添加分页功能 （使用PageHelper，忽略）
//	    sqlSessionFactory.setPlugins(new Interceptor[]{
//	    	mybatisPlusInterceptor()
//	    });
			    
	    return sqlSessionFactory.getObject();
	}
	
}
